/*
 * Copyright (C) 2012 rothens
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package rpg.ui.components;

import rpg.gfx.Bitmap;
import rpg.util.BoundingBox;
import rpg.util.MathUtil;

/**
 *
 * @author rothens
 */
public class ComponentSlider extends Component implements IDraggableComponent {

    boolean dragged = false;
    public Bitmap knob = new Bitmap(32, 32, StaticTextures.slider[0]);
    public Bitmap truck;
    int prevX;
    private int knobPos = 0;
    private BoundingBox knobBB;
    private int leftValue;
    private int rightValue;
    private int step;
    
    private int spacing;
    private int ldiff;
    private double values;
    private int value;

    public ComponentSlider(Integer x, Integer y, int size, int leftValue, int rightValue, int step) {
        super(size + 16, 32, x, y);
        if (leftValue >= rightValue) {
            throw new IllegalArgumentException("leftValue must be smaller than rightValue!");
        }
        if (step < 1) {
            throw new IllegalArgumentException("step must be a positive integer!");
        }
        this.leftValue = leftValue;
        this.rightValue = rightValue;
        this.step = step;
        truck = new Bitmap(size, 8);
        truck.draw(StaticTextures.slider[1], 0, 0);
        truck.draw(StaticTextures.slider[2], size - 8, 0);
        truck.draw(new Bitmap(size - 16, 8, StaticTextures.slider[3]), 8, 0);
        createNotches();
        jumpToNotch(0);
        knobBB = new BoundingBox(this.x + knobPos, this.y, 32, 32);
        redraw();
    }

    @Override
    public void redraw() {
        clear();
        drawOn(truck, 8, 12);
        drawOn(knob, knobPos, 0);
        if(parent != null){
            ((Component)parent).redraw();
        }
    }

    @Override
    public void onStartDrag(int x, int y) {
        if (!knobBB.isMouseOver(x, y)) {
            knobPos = MathUtil.clamp(0, width - 32, x - this.x - 16);

        }
        dragged = true;
        prevX = x;
    }

    @Override
    public void whileDrag(int x, int y) {
        if (prevX == x) {
            return;
        }
        final int diff = x - prevX;
        knobPos = MathUtil.clamp(0, width - 32, knobPos + diff);
        prevX = x;

    }

    @Override
    public void onEndDrag(int x, int y) {
        dragged = false;
        updateBB();
        jumpToNotch(getNearestNotch());
    }

    @Override
    public boolean isDragged() {
        return dragged;
    }

    public void updateBB() {
        knobBB.setX(this.x + knobPos);
    }

    public void knobLocationPercent() {
        int prc = (int) (((double) knobPos / (double) (width - 32)) * 100);
        System.out.println(prc + "%");
    }

    public void createNotches() {
        values = (rightValue+step - leftValue) / step;
        spacing = (int) Math.ceil((double) (truck.width - 16) / values);
        ldiff = ((truck.width - 16) - (int) (values-1) * spacing) / 2;
        for (int i = 0; i < values; i++) {
            truck.drawOn(StaticTextures.slider[4], i * spacing + 7 + ldiff, 0);
        }
    }
    
    public int getNearestNotch(){
        int ret = (knobPos-ldiff+spacing/2)/spacing;
        ret = MathUtil.clamp(0, (int)values-1, ret);
        return ret;        
    }
    
    public void jumpToNotch(int i){
        if(i<0 || i>= values){
            throw new IllegalArgumentException("Notch index out of bounds: " + i);
        }
        int location = i*spacing+ldiff;
        knobPos = location;
        value = calculateValue();
    }
    
    public int calculateValue(){
        int n = getNearestNotch();
        int val = leftValue + n * step;
        return val;
    }
    
    
}
